package com.zzg.demo.springbatch;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.*;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.JobOperator;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

@RestController
@RequestMapping("/springbatch")
@Slf4j
public class TestSpringBatchController {
    @Resource
    private JobLauncher myJobLauncher;
    @Resource
    private Job changePersonInfoJob;
    @Resource
    private JobOperator jobOperator;
    @Resource
    private JobExplorer jobExplorer;

    /**
     * 生成一个任务并运行
     * 每次运行timestamp和run.id都自动生成，所以每次运行都是相当于创建一个新的任务实例
     * @throws Exception
     */
    @GetMapping("/testdemo")
    public  void testJob() throws Exception {
        log.info("testdemo-开始执行spring batch批处理。。。");
        // 后置参数：使用JobParameters中绑定参数 addLong  addString 等方法
        JobParameters jobParameters = new JobParametersBuilder()
                .addLong("timestamp", System.currentTimeMillis())
                .addString("run.id", UUID.randomUUID().toString())  // 添加唯一标识
                .toJobParameters();
        JobExecution jobExecution = myJobLauncher.run(changePersonInfoJob, jobParameters);
        log.info("testdemo-批处理执行结束：Job Exit Status=" + jobExecution.getStatus());
    }

    /**
     * 生成一个任务并运行
     * 可以自定义传入参数，如果多次运行，但是参数都一样，则认为是同个任务但是不同的运行
     * @param params
     * @throws Exception
     */
    @GetMapping("/testdemowithparams")
    public void testJobWithParams(@RequestParam Map<String, Object> params) throws Exception {
        log.info("testdemowithparams-开始执行spring batch批处理。。。");
        // 后置参数：使用JobParameters中绑定参数 addLong  addString 等方法
        JobParametersBuilder builder = new JobParametersBuilder();
        // 添加自定义参数
        params.forEach((key, value) -> builder.addString(key, value.toString()));
        JobExecution jobExecution = myJobLauncher.run(changePersonInfoJob, builder.toJobParameters());
        log.info("testdemowithparams-批处理执行结束：Job Exit Status=" + jobExecution.getStatus());
    }

    /**
     * 重启一个任务
     * @param jobExecutionId
     * @return
     */
    @GetMapping("/restart/{jobExecutionId}")
    public String restartJobByExecutionId(@PathVariable Long jobExecutionId) {
        try {
            jobOperator.restart(jobExecutionId);
            return "Job restart initiated，jobExecutionId=" + jobExecutionId;
        } catch (Exception e) {
            return "Failed to restart job: " + e.getMessage();
        }
    }

    /**
     * 查询任务状态
     * @param jobExecutionId
     * @return
     */
    @GetMapping("/status/{jobExecutionId}")
    public String getJobStatus(@PathVariable Long jobExecutionId) {
        JobExecution jobExecution = jobExplorer.getJobExecution(jobExecutionId);
        if (jobExecution != null) {
            return "Job Status: " + jobExecution.getStatus() +
                    ", Exit Status: " + jobExecution.getExitStatus();
        }
        return "Job execution not found";
    }

    /**
     * 查询任务执行的上下文（包括任务级别和步骤级别）
     * @param jobExecutionId
     */
    @GetMapping("/printContext/{jobExecutionId}")
    public void printContext(@PathVariable Long jobExecutionId) {
        JobExecution jobExecution = jobExplorer.getJobExecution(jobExecutionId);
        ExecutionContext jobContext = jobExecution.getExecutionContext();
        log.info("Job Context: " + jobContext.entrySet());

        for (StepExecution stepExecution : jobExecution.getStepExecutions()) {
            ExecutionContext stepContext = stepExecution.getExecutionContext();
            log.info("Step Context (Step " + stepExecution.getStepName() + "): " + stepContext.entrySet());
        }
    }
}
